package com.sixbro.authorization.security.config;

import com.sixbro.common.constant.AuthConstants;
import com.sixbro.authorization.security.component.AppAccessTokenConverter;
import com.sixbro.authorization.security.domain.OAuth2UserDetails;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;

import java.security.KeyPair;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 *
 * </p>
 *
 * @author: Mr.Lu
 * @since: 2021/6/15 14:26
 */
@Configuration
public class TokenStoreAutoConfigure {

    /**
     * access_token存储器
     * 这里存储在数据库，大家可以结合自己的业务场景考虑将access_token存入数据库还是redis
     */
    @Bean
    public TokenStore tokenStore(){
        return new JwtTokenStore(accessTokenConverter());
    }

    /**
     * jwt生成使用RS256非对称加密，非对称加密需要私钥和公钥，此处设置公钥
     */
    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter(){

            /**
             * 重写增强token方法,用于自定义一些token返回的信息
             *
             * @param accessToken
             * @param authentication
             * @return
             */
            @Override
            public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
                OAuth2UserDetails OAuth2UserDetails = (OAuth2UserDetails) authentication.getUserAuthentication().getPrincipal();
                final Map<String,Object> additionalInformation = new HashMap<>(4);
                additionalInformation.put(AuthConstants.DETAILS_USER_ID_KEY, OAuth2UserDetails.getId());
                additionalInformation.put(AuthConstants.DETAILS_MOBILE_KEY, OAuth2UserDetails.getMobile());
                additionalInformation.put(AuthConstants.DETAILS_TENANT_ID_KEY, OAuth2UserDetails.getMobile());

                ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInformation);
                return super.enhance(accessToken, authentication);
            }
        };
        //  非对称密钥加密
        accessTokenConverter.setKeyPair(keyPair());
        accessTokenConverter.setAccessTokenConverter(new AppAccessTokenConverter());
        return accessTokenConverter;
    }

    /**
     * 从classpath下的密钥库中获取密钥对(公钥+私钥)
     */
    @Bean
    public KeyPair keyPair() {
        KeyStoreKeyFactory factory = new KeyStoreKeyFactory(new ClassPathResource("jwt.jks"), "123456".toCharArray());
        return factory.getKeyPair("jwt", "123456".toCharArray());
    }
}